package main

import (
	"bufio"
	"fmt"
	"io"
	"log"
	"logparser/entity"
	"os"
	"regexp"
	"strings"

	_ "github.com/go-sql-driver/mysql"
	"github.com/jmoiron/sqlx"
)

var Db *sqlx.DB

var filename = "./log.sql"
var config *entity.Config

func init() {
	config = entity.NewConfig()
	config = config.GetConf()

	database, err := sqlx.Open("mysql", config.Datasource)
	if err != nil {
		fmt.Println("open mysql failed,", err)
		return
	}
	Db = database
}

func main() {
	ReadLine()
}

func ReadLine() {
	file, _ := os.Open(config.Logpath)
	fileScanner := bufio.NewScanner(file)
	output, _ := os.Create(filename) //创建文件
	defer output.Close()
	defer file.Close()
	defer Db.Close() // 注意这行代码要写在上面err判断的下面

	index := 0
	sharpIndex := 0
	nosharpIndex := 0

	logs := []string{}

	for fileScanner.Scan() {
		lineText := strings.TrimSpace(fileScanner.Text())
		log.Println(lineText)
		index++
		// if index > 20 {
		// 	break
		// }
		//if strings.HasPrefix(lineText, "SET") {
		//	continue
		//}
		// log.Println(lineText)
		// 碰到# 开始缓存
		if strings.HasPrefix(lineText, "#") {
			sharpIndex = sharpIndex + 1
			nosharpIndex = 0
		} else {
			sharpIndex = 0
			nosharpIndex = nosharpIndex + 1
		}
		// log.Println(sharpIndex, nosharpIndex)

		if sharpIndex == 1 && nosharpIndex == 0 && len(logs) > 0 {
			doGenSql(logs, output)
			logs = logs[0:0]
		}

		logs = append(logs, lineText)
	}
}

var useBb string

// 生成sql
func doGenSql(logs []string, f io.Writer) {
	log.Println("========")
	data := &Data{}
	for index := range logs {
		text := logs[index]
		log.Println(text)
		text = strings.Replace(text, "# ", "", 1)

		rule, _ := regexp.Compile("[ ]+")
		text = rule.ReplaceAllString(text, " ")
		text_slice := strings.Split(text, " ")
		// fmt.Println("result1:", text_slice[0])
		if text_slice[0] == "Time:" {
			data.time = text_slice[1]
		}

		if text_slice[0] == "use" {
			useBb = text_slice[1]
		}
		data.useDb = useBb
		log.Println("use:", useBb)

		if text_slice[0] == "SET" {
			timestampStr := text_slice[1]
			//log.Println(timestampStr)
			timestampSlice := strings.Split(timestampStr, "=")
			//log.Println(timestampSlice)
			data.timestamp = timestampSlice[1]
		}

		if text_slice[0] == "User@Host:" {
			data.user = text_slice[1]
			data.host = text_slice[3]
		}

		if text_slice[0] == "Query_time:" && len(text_slice) > 7 {
			data.queryTime = text_slice[1]
			data.lockTime = text_slice[3]
			data.rowSent = text_slice[5]
			data.rowExamined = text_slice[7]
		}

		sqlText := strings.ToLower(text_slice[0])
		if sqlText == "delete" || sqlText == "select" || sqlText == "update" || sqlText == "insert" {
			data.sqlString = strings.Replace(strings.Join(text_slice, " "), "'", "`", -1)
			log.Println(data.sqlString)
			for i := range text_slice {
				sqlTx := text_slice[i]
				if sqlTx == "FROM" || sqlTx == "from" {
					if len(text_slice) < i+1 {
						log.Println(text_slice)
						panic("wrong")
					}
					if len(text_slice) > i+1 {
						data.tableName = text_slice[i+1]
						break
					}
				}
			}
		}
		// fmt.Println("result:", text_slice)
		// fmt.Println("len:", len(text_slice))
		// fmt.Println("cap:", cap(text_slice))
	}
	//log.Println("data:", data)

	if data.time == "" {
		return
	}

	sql := "insert into t_slowlog(useDb, time, timestampStr, user, ip, queryTime, lockTime, rowSent, rowExamined, sqlString, tableName) values('" +
		data.useDb + "', '" +
		data.time + "', '" +
		data.timestamp + "', '" +
		data.user + "', '" +
		data.host + "', '" +
		data.queryTime + "', '" +
		data.lockTime + "', '" +
		data.rowSent + "', '" +
		data.rowExamined + "', '" +
		data.sqlString + "', '" +
		data.tableName + "') \r\n"

	log.Println("sql:", sql)
	//w := bufio.NewWriter(f) //创建新的 Writer 对象
	//n4, _ := w.WriteString(sql)
	//fmt.Printf("写入 %d 个字节n", n4)
	//w.Flush()

	r, err := Db.Exec(sql)
	if err != nil {
		fmt.Println("exec failed, ", err)
		return
	}
	id, _ := r.LastInsertId()
	fmt.Println("insert succ:", id)
	log.Println("========")
}

type Data struct {
	useDb       string
	time        string
	timestamp   string
	user        string
	host        string
	queryTime   string
	lockTime    string
	rowSent     string
	rowExamined string
	tableName   string
	sqlString   string
}
